package xyz.fefine;

import javax.print.attribute.standard.MediaSize;
import java.util.ArrayList;
import java.util.List;

/**
 * 传递给函数的参数
 * Created by feng_ on 2016/9/11.
 */
public class Arguments extends  Postfix{
    public Arguments(List<ASTree> list) {
        super(list);
    }

    public Arguments() {
        super(new ArrayList<>());
    }
    public int size() {
        return super.numChildren();
    }

    @Override
    public Object eval(Enviorment enviorment) {
        Object res = null;
        for (ASTree asTree : children) {
            res = asTree.eval(enviorment);
        }
        return res;
    }

    @Override
    public Object eval(Enviorment env, Object value) {
        //value必须是function类型
        if (value instanceof Function) {
            //采用新的fun对象,
            Function func = (OpFunction)value;
            ParameterList ps = func.getParameters();
            if (size() != ps.size()) {
                throw new StoneException("bad number of arguments",this);
            }
            //这里的env是ArrayEnv
            Enviorment newEnv = func.makeEnv();
            int num = 0;
            //无参数时不执行,根据传递进来的实参进行判断
            //定义时 params_list中会含有NullStmnt,会有长度
            for (ASTree e : this.children) {
                //将参数放进新的定义域
                //e.eval(env)返回expr的执行结果
                ps.eval(newEnv, num++, e.eval(env));
            }
            return func.body.eval(newEnv);
        } else if (value instanceof NativeFunction) {

            NativeFunction function = (NativeFunction)value;
            int params = function.getNumParams();
            if (size() != params) {
                throw new StoneException("bad number of arguments",this);
            }
            Object[] args = new Object[params];
            int num = 0;
            for (ASTree asTree : this.children) {
                args[num++] = asTree.eval(env);
            }
            return function.invoke(args, this);
        }
        throw new StoneException("bad function", this);
    }

    //    @Override
//    public String toString() {
//        StringBuilder sb = new StringBuilder("(");
//        for (ASTree asTree : super.children) {
//            sb.append(asTree+",");
//        }
//        sb.append(")");
//        return sb.toString();
//    }
}
